c->x86 == 0x17)
detect_zen2_null_seg_behaviour();
+ /*
+ * AMD CPUs before Zen2 don't clear segment bases/limits when loading
+ * a NULL selector.
+ */
+ if (c == &boot_cpu_data && !cpu_has_nscb)
+ setup_force_cpu_cap(X86_BUG_NULL_SEG);
+
/* MFENCE stops RDTSC speculation */
if (!cpu_has_lfence_dispatch)
__set_bit(X86_FEATURE_MFENCE_RDTSC, c->x86_capability);
c->x86 == 0x18)
detect_zen2_null_seg_behaviour();
+ /*
+ * Hygon CPUs before Zen2 don't clear segment bases/limits when
+ * loading a NULL selector.
+ */
+ if (c == &boot_cpu_data && !cpu_has_nscb)
+ setup_force_cpu_cap(X86_BUG_NULL_SEG);
+
/* MFENCE stops RDTSC speculation */
if (!cpu_has_lfence_dispatch)
__set_bit(X86_FEATURE_MFENCE_RDTSC, c->x86_capability);
if ( sel > 3 )
/* Fix up RPL for non-NUL selectors. */
sel |= 3;
- else if ( boot_cpu_data.x86_vendor &
- (X86_VENDOR_AMD | X86_VENDOR_HYGON) )
+ else if ( cpu_bug_null_seg )
/* Work around NUL segment behaviour on AMD hardware. */
asm volatile ( "mov %[sel], %%gs"
:: [sel] "r" (FLAT_USER_DS32) );
/* Bugs. */
#define cpu_bug_fpu_ptrs boot_cpu_has(X86_BUG_FPU_PTRS)
+#define cpu_bug_null_seg boot_cpu_has(X86_BUG_NULL_SEG)
enum _cache_type {
CACHE_TYPE_NULL = 0,
#define X86_BUG(x) ((FSCAPINTS + X86_NR_SYNTH) * 32 + (x))
#define X86_BUG_FPU_PTRS X86_BUG( 0) /* (F)X{SAVE,RSTOR} doesn't save/restore FOP/FIP/FDP. */
+#define X86_BUG_NULL_SEG X86_BUG( 1) /* NULL-ing a selector preserves the base and limit. */
/* Total number of capability words, inc synth and bug words. */
#define NCAPINTS (FSCAPINTS + X86_NR_SYNTH + X86_NR_BUG) /* N 32-bit words worth of info */